/**
`useLayoutEffect`  是 React 中的一个 Hook，用于在 DOM 更新后立即同步执行副作用。它的作用类似于  `useEffect` ，但是它会在浏览器绘制之前执行，因此可以用于需要在浏览器绘制之前读取布局和同步更新的场景。
  1. 基本概念

  - 同步副作用： `useLayoutEffect`  允许你在 DOM 更新后、浏览器绘制之前执行副作用。这使得你可以读取 DOM 的布局并进行同步更新，确保在用户看到更新之前完成所有必要的计算和渲染。
  - 使用方式：它的使用方式与  `useEffect`  相同，但通常用于需要同步更新的场景。

  2. 使用方式
   示例：动态调整元素位置
  import React, { useLayoutEffect, useRef, useState } from 'react';

  const LayoutEffectExample = () => {
    const [width, setWidth] = useState(0);
    const boxRef = useRef();

    useLayoutEffect(() => {
      // 在浏览器绘制之前读取 DOM 的宽度
      const boxWidth = boxRef.current.getBoundingClientRect().width;
      setWidth(boxWidth);
    }, []); // 仅在组件挂载时执行

    return (
      <div>
        <div ref={boxRef} style={{ width: '50%', height: '100px', backgroundColor: 'lightblue' }}>
          This box's width is {width}px
        </div>
      </div>
    );
  };

  export default LayoutEffectExample;
  3. 适用场景

  - 读取布局信息：当你需要在渲染后立即读取 DOM 元素的布局（如宽度、高度等）并进行相应的计算时，使用  `useLayoutEffect`  是合适的。
  - 避免闪烁：在某些情况下，如果使用  `useEffect` ，可能会导致用户在页面上看到不一致的状态或闪烁。 `useLayoutEffect`  可以确保在浏览器绘制之前完成所有更新，从而避免这种情况。

  4. 注意事项
  - 性能影响：由于  `useLayoutEffect`  会在浏览器绘制之前执行，因此可能会影响性能，尤其是在大型组件树中。应谨慎使用，避免在不必要的情况下使用。
  - 与  `useEffect`  的区别： `useEffect`  在 DOM 更新后异步执行，而  `useLayoutEffect`  是同步执行的。通常情况下，优先使用  `useEffect` ，只有在需要同步读取布局时才使用  `useLayoutEffect` 。

  5. 总结
  `useLayoutEffect`  是一个强大的工具，允许开发者在 DOM 更新后、浏览器绘制之前执行同步副作用。它主要用于需要立即读取布局信息并进行更新的场景。合理使用  `useLayoutEffect`  可以提高用户体验，避免不必要的闪烁和布局问题，但也要注意其对性能的潜在影响。

  useLayoutEffect和useEffect的区别：
  - useLayoutEffect在浏览器绘制之前执行，而useEffect在浏览器绘制之后执行。
  - useLayoutEffect可以同步读取DOM布局信息，而useEffect不能。
  - useLayoutEffect可能会影响性能，因此应谨慎使用。
 */
import React, { memo, useEffect, useLayoutEffect, useState } from 'react'

const App = memo(() => {
  const [count, setCount] = useState(0)

  useLayoutEffect(() => {
    console.log('useLayoutEffect')
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  }, [count])

  useEffect(() => {
    console.log('useEffect')
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  }, [count])
  
  console.log('App render');

  return (
    <div>
      <h2>01_layoutEffect和Effect时机: {count}</h2>
      <p>执行顺序： App render -》 useLayoutEffect -》 useEffect</p>
      <button onClick={e => setCount(count + 1)}>+1</button>

      <h2>02_切换数字-useEffect: {count}</h2>  
      <button onClick={e => setCount(0)}>设置为0</button>

      <h2>03_切换数字-useLayoutEffect: {count}</h2>  
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App